package com.fxm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fxm.dao.RankMapper;
import com.fxm.domain.Rank;
import com.fxm.domain.Record;
import com.fxm.domain.User;
import com.fxm.returns.RespCode;
import com.fxm.returns.RespEntity;
import com.fxm.service.RankService;
import com.fxm.service.RecordService;
import com.fxm.service.UserService;
import com.fxm.utils.TimeUtilCustomize;
import com.fxm.vo.RankVO;
import com.fxm.vo.param.RankParam;
import com.fxm.vo.result.RankResult;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RankServiceImpl extends ServiceImpl<RankMapper, Rank> implements RankService {

    @Autowired
    private UserService userService;

    @Autowired
    private RecordService recordService;

    @Override
    public Rank getRankByOpenidAndDate(String openid, String date) {
        return baseMapper.getRankByOpenidAndDate(openid, date);
    }

    @Override
    public void updateRank(Rank rank) {
        baseMapper.updateRank(rank);
    }

    @Override
    public void insertRank(Rank rank) {
        baseMapper.insertRank(rank);
    }

    @Override
    public RespEntity<List<RankResult>> listRank(RankParam rankParam) {
        if (Objects.isNull(rankParam) || Objects.isNull(rankParam.getPage())) {
            return new RespEntity<>(RespCode.PARAMETERS_ERROR);
        }

        List<RankResult> rankResultList = Lists.newArrayList();
        switch (rankParam.getPage()) {
            case 0 : rankResultList = getAllRank(); break;
            case 1 : rankResultList = getTodayAnswer(); break;
            case 2 : rankResultList = maxHistoryAnswer(); break;
            case 3 : rankResultList = maxErrorAnswer(); break;
            case 4 : rankResultList = maxWinAnswer();
        }

        //按照value字段值 降序排列 取前10
        rankResultList = rankResultList.stream()
                .sorted(Comparator.comparing(RankResult::getValue).reversed())
                .limit(10)
                .collect(Collectors.toList());

        for (int i = 0; i < rankResultList.size(); i++) {
            Integer index = i + 1;
            rankResultList.get(i).setId(index);
        }

        return new RespEntity<>(RespCode.SUCCESS, rankResultList);
    }

    /**
     * 积分排名
     * @return
     */
    private List<RankResult> getAllRank() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getDeleted, 0);
        List<User> userList = userService.list(queryWrapper);

        if (Objects.isNull(userList) || CollectionUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }

        List<RankResult> rankResultList = Lists.newArrayList();

        userList.forEach(user -> {
            RankResult rankResult = new RankResult();
            rankResult.setName(user.getUsername());
            rankResult.setValue(user.getIntegral());
            rankResult.setUrl(user.getPicPath());
            rankResultList.add(rankResult);
        });

        return rankResultList;
    }

    /**
     * 每日答题
     * @return
     */
    private List<RankResult> getTodayAnswer() {
        String begin = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, new Date());
        String end = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_TIME_FORMAT, new Date());

        List<RankVO> rankVOList = recordService.todayAnswer(begin, end);

        if (Objects.isNull(rankVOList) || CollectionUtil.isEmpty(rankVOList)) {
            return new ArrayList<>();
        }

        List<RankResult> rankResultList = Lists.newArrayList();
        rankVOList.forEach(rankVO -> {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(User::getOpenid, rankVO.getOpenid())
                    .eq(User::getDeleted, 0);
            User user = userService.getOne(queryWrapper);

            if (Objects.nonNull(user)) {
                RankResult rankResult = new RankResult();
                rankResult.setName(user.getUsername());
                rankResult.setValue(rankVO.getValue());
                rankResult.setUrl(user.getPicPath());
                rankResultList.add(rankResult);
            }
        });

        return rankResultList;
    }

    /**
     * 最多答题
     * @return
     */
    private List<RankResult> maxHistoryAnswer() {
        List<RankVO> rankVOList = recordService.maxHistoryAnswer();

        if (Objects.isNull(rankVOList) || CollectionUtil.isEmpty(rankVOList)) {
            return new ArrayList<>();
        }

        List<RankResult> rankResultList = Lists.newArrayList();
        rankVOList.forEach(rankVO -> {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(User::getOpenid, rankVO.getOpenid())
                    .eq(User::getDeleted, 0);
            User user = userService.getOne(queryWrapper);

            if (Objects.nonNull(user)) {
                RankResult rankResult = new RankResult();
                rankResult.setName(user.getUsername());
                rankResult.setValue(rankVO.getValue());
                rankResult.setUrl(user.getPicPath());
                rankResultList.add(rankResult);
            }
        });

        return rankResultList;
    }

    /**
     * 最多连败
     * @return
     */
    private List<RankResult> maxErrorAnswer() {
        String date = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, new Date());
        List<Rank> rankList = baseMapper.listMaxWinAndError(date);

        if(checkErrorEmpty(rankList)){
            Date dayFromToday = TimeUtilCustomize.getDayFromToday(1);
            String yesterday = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, dayFromToday);
            rankList = baseMapper.listMaxWinAndError(yesterday);
        }

        List<RankResult> rankResultList = Lists.newArrayList();
        rankList.forEach(rank -> {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(User::getOpenid, rank.getOpenid())
                    .eq(User::getDeleted, 0);
            User user = userService.getOne(queryWrapper);

            if (Objects.nonNull(user)) {
                RankResult rankResult = new RankResult();
                rankResult.setName(user.getUsername());
                rankResult.setValue(rank.getMaxError());
                rankResult.setUrl(user.getPicPath());
                rankResultList.add(rankResult);
            }
        });

        return rankResultList;
    }

    private boolean checkErrorEmpty( List<Rank> rankList) {
        boolean flag = true;
        for (Rank rank : rankList) {
            if (!rank.getMaxError().equals(0)) {
               flag = false;
               break;
            }
        }
        return flag;
    }

    /**
     * 最多连胜
     * @return
     */
    private List<RankResult> maxWinAnswer() {
        String date = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, new Date());
        List<Rank> rankList = baseMapper.listMaxWinAndError(date);

        if(checkWinEmpty(rankList)){
            Date dayFromToday = TimeUtilCustomize.getDayFromToday(1);
            String yesterday = TimeUtilCustomize.parseDateToStr(TimeUtilCustomize.DATE_DAY_FORMAT, dayFromToday);
            rankList = baseMapper.listMaxWinAndError(yesterday);
        }

        List<RankResult> rankResultList = Lists.newArrayList();
        rankList.forEach(rank -> {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(User::getOpenid, rank.getOpenid());
            User user = userService.getOne(queryWrapper);

            if (Objects.nonNull(user)) {
                RankResult rankResult = new RankResult();
                rankResult.setName(user.getUsername());
                rankResult.setValue(rank.getMaxCorrect());
                rankResult.setUrl(user.getPicPath());
                rankResultList.add(rankResult);
            }
        });

        return rankResultList;
    }

    private boolean checkWinEmpty( List<Rank> rankList) {
        boolean flag = true;
        for (Rank rank : rankList) {
            if (!rank.getMaxCorrect().equals(0)) {
                flag = false;
                break;
            }
        }
        return flag;
    }
}
